package trie;

import java.io.IOException;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;

import strategies.IActionAtInsert;

import logging.Log;

class TrieNode implements ITrieNode {

	Object value; // richtiger Schl�ssel des Wortes; hier Char des Wortes als
					// Integer
	TrieNode parent; // elternknoten des aktuellen

	TreeMap<Comparable, TrieNode> partOfKeyToTrieNode; // TreeMap<Character
														// d.Wortes , Verweis
														// auf n�chsten Knoten>
	static final boolean traceFlag = true;

	public TrieNode(TrieNode parent) {
		this.parent = parent;
		partOfKeyToTrieNode = new TreeMap<Comparable, TrieNode>();
	}

	/**
	 * Methode zum einstellen der Buchstaben in den Baum.
	 * 
	 * @param key
	 *            : It erator, in dem die Buchstaben des Wortes als Integer
	 *            hinterlegt sind
	 * @param value
	 *            : Schl�ssel des Gesamtwortes
	 * @return
	 */
	
	public TrieReference recursiveInsert(Iterator key,
			IActionAtInsert valueAddingStrategy) {
		int current = (int) key.next();
		if (traceFlag) {

			Log.println(TrieNode.class, "recursiceInsert", 1,
					"hier wird der char "+ (char)current+" aufgerufen" , true);

		}
		
		TrieReference trieReference = null;
		boolean found = true;

		if (!key.hasNext()) {

			if (!partOfKeyToTrieNode.containsKey(current)) {
				partOfKeyToTrieNode.put(current, new TrieNode(this));
				System.out.println("Char ist nicht im Baum. "
						+ "= > Es wird ein neuer Knoten erstellt.");
			}

			if (partOfKeyToTrieNode.get(current).getValue() == null) {
				partOfKeyToTrieNode.get(current).setValue(valueAddingStrategy.actionInCaseOfNotFoundKey());
				System.out
						.println("Char ist im Baum. => neuer Value des Wortes:"
								+ partOfKeyToTrieNode.get(current).getValue());
				found = false;
			} else {
				partOfKeyToTrieNode.get(current).setValue(valueAddingStrategy.actionInCaseOfFoundKey(partOfKeyToTrieNode.get(current).getValue()));
				found = true;
			}

			trieReference = new TrieReference(found, partOfKeyToTrieNode.get(current).getValue());
			System.out.println("aktuelle Reference:: Found:"
					+ trieReference.getFound() + " val:"
					+ trieReference.getValue());
			System.out.println("letzter CHAR! Value=" + partOfKeyToTrieNode.get(current).getValue() + "\n\n");
			
		}
		// es gibt weitere Elemente im Trie
		while (key.hasNext()) {

			// aktueller Key darf nicht in der Map enthalten sein => sont keine
			// Einf�gen
			if (!partOfKeyToTrieNode.containsKey(current)) {
				partOfKeyToTrieNode.put(current, new TrieNode(this));
				System.out.println("Char ist nicht im Baum. "
						+ "= > Es wird ein neuer Knoten erstellt.");
				trieReference = partOfKeyToTrieNode.get(current).recursiveInsert(key,
						valueAddingStrategy);
			} else {
				System.out
						.println("Char bereits im Baum. Rufe nächsten Node auf.");
				trieReference = partOfKeyToTrieNode.get(current).recursiveInsert(key,
						valueAddingStrategy);
			}
		}

		return trieReference;

	}

	/**
	 * Methode zum debuggen des Iterators
	 * 
	 * @param key
	 *            :: Iterator der abgerufen wird
	 */
	void iteratorDebug(Iterator key) {
		while (key.hasNext()) {
			System.out.println("Suche nach: " + key.next());
		}
		
	}

	@Override
	public Object recursiveLookup(Iterator key) {
		int current = (int) key.next();

		if (!key.hasNext()) {
			if (this.value != null)
				return value;
		}

		while (key.hasNext()) {
			if (partOfKeyToTrieNode.containsKey(current)) {
				partOfKeyToTrieNode.get(current).recursiveLookup(key);
			}
		}
		return null;
	}

	// Prüft ob schlüssel bereits im Baum eingetragen
	public boolean hasKey(Comparable value) {
		Set<Comparable> a = partOfKeyToTrieNode.keySet();
		Iterator it = a.iterator();
		if (recursiveLookup(it) != null)
			return true;
		else
			return false;
	}

	public String toString(int depth) {
		depth++;
		String temp = "";
		Set<Comparable> a = partOfKeyToTrieNode.keySet();
		Iterator it = a.iterator();
		// iteratorDebug(it);
		while (it.hasNext()) {
			int ascii = (int) it.next();
			char ch = (char) ascii;
			for (int i = 1; i < depth; i++) {
				temp += ".";
			}
			temp += ch;
			if (partOfKeyToTrieNode.get(ascii).getValue() != null) {
				temp += " --> " + partOfKeyToTrieNode.get(ascii).getValue();
			}
			temp += "\n";
			temp += partOfKeyToTrieNode.get(ascii).toString(depth);

		}

		return temp;
	}
	public void setValue(Object value ){
		this.value = value;
	}
	public Object getValue(){
		return value;
	}

	public String recursiveLookup2(int decoderInt) {
		// TODO Auto-generated method stub
		return null;
	}
}
